using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

namespace KFGame
{

    /// <summary>
    /// 场景管理
    /// </summary>
    [DisallowMultipleComponent]
    public class KFSceneManager : MonoBehaviour
    {
        private static KFSceneManager _scenes;
        public static KFSceneManager scenesManager
        {
            get
            {
                if (_scenes == null)
                    _scenes = new KFSceneManager();
                return _scenes;
            }

        }

        //上一个主场景
        public string previousScene;
        //正在激活的 活动的场景
        [HideInInspector]
        public string activeScene = null;
        //己加载的场景资源
        private List<string> loadedScenes = new List<string>();

        void Awake()
        {
            _scenes = this;
            //场景管理器
            SceneManager.sceneLoaded += OnSceneLoaded;
            SceneManager.sceneUnloaded += OnSceneUnLoaded;
            SceneManager.activeSceneChanged += OnActiveSceneChanged;
        }

        /// <summary>
        /// 他建一个新场景
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public Scene CreateScene(string name)
        {
            Scene scene = SceneManager.CreateScene(name);
            addSceneName(scene.name);
            return scene;
        }

        /// <summary>
        /// 添加模式进行加载 加载进场景 
        /// /// </summary>
        /// <param name="scene">场景 必需要在场景管理器中存在</param>
        /// <param name="visable">加载后是否可见</param>
        /// <param name="active">加载后是否激活状态</param>
        public void laodAddScene(string scene, bool visable = true, bool active = false)
        {
            if (name == null)
                return;

            if (active)
                activeScene = name;

            loadscene.Add(scene, visable);

            SceneManager.LoadScene(name, LoadSceneMode.Additive);
        }

        /// <summary>
        ///  加载场景 （名字，是否激活， 单专场景模式 ）
        /// </summary>
        /// <param name="name">场景名字</param>
        /// <param name="setActive">是否激活 isSingle 需要设为false </param>
        /// <param name="isSingle">单专场景模式, </param>
        public void LoadScene(string name, bool setActive = true, bool isSingle = true)
        {
            if (name == null)
            {
                KF.Log("can't load scene : name->" + name + "　action->" + setActive + "  isSingle->" + isSingle);
                return;
            }

            if (isSingle)
            {
                SceneManager.LoadScene(name);
                return;
            }

            if (setActive)
                activeScene = name;

            KF.Log(" load scene : name->" + name + "　action->" + setActive + "  isSingle->" + isSingle);
            SceneManager.LoadScene(name, LoadSceneMode.Additive);

        }


        /// <summary>
        ///  场景是否己加载
        /// </summary>
        /// <param name="name"></param>
        public bool SceneContains(string name)
        {
            return loadedScenes.Contains(name);
        }
        /// <summary>
        /// 把场景添加到管理中
        /// </summary>
        /// <param name="name"></param>
        public void addSceneName(string name)
        {
            if (loadedScenes.Contains(name))
                return;
            loadedScenes.Add(name);
        }
        /// <summary>
        /// 移除后除了框加之外的所有场景资源 
        /// </summary>
        public void UnloadAllScene()
        {
            for (int i = 0; i < loadedScenes.Count; i++)
                UnLoadScene(loadedScenes[i]);
        }

        /// <summary>
        /// 移除场景资源
        /// </summary>
        /// <param name="name"></param>
        public void UnLoadScene(string name)
        {
            if (SceneManager.GetActiveScene().name != name)
                SceneManager.UnloadSceneAsync(name);
        }

        public static void MoveGameObjectToScene(GameObject go, Scene sc)
        {
            SceneManager.MoveGameObjectToScene(go, sc);
        }

        public struct SceneObject
        {
            public GameObject obj;
            public bool visable;

            public void hiden()
            {
                if (obj != null)
                    obj.SetActive(false);
            }
            public void show()
            {
                obj.SetActive(visable);
            }
        }

        /// <summary>
        /// 隐藏的场景
        /// </summary>
        /// <returns></returns>
        private Dictionary<Scene, List<SceneObject>> hidenScenes = new Dictionary<Scene, List<SceneObject>>();
        /// <summary>
        /// 加载的列表
        /// </summary>
        /// <typeparam name="string"></typeparam>
        /// <typeparam name="bool"></typeparam>
        /// <returns></returns>
        private Dictionary<string, bool> loadscene = new Dictionary<string, bool>();

        /// <summary>
        /// 加载某一场景的进度，
        /// </summary>
        /// <param name="scene"></param>
        /// <param name="progress"></param>
        public delegate void LoadProgress(string scene, float progress);
        public LoadProgress onLoadProgresss;


        /// <summary>
        /// 隐藏所有
        /// </summary>
        public void hideAll()
        {

            for (var i = 0; i < SceneManager.sceneCount; i++)
                hideSecen(SceneManager.GetSceneAt(i));

        }

        /// <summary>
        /// 显示所有隐藏的
        /// </summary>
        public void visableAll()
        {
            foreach (var scene in hidenScenes.Keys)
            {
                var list = hidenScenes[scene];
                foreach (var l in list)
                    l.show();
            }

            hidenScenes.Clear();
        }

        /// <summary>
        /// 隐藏场景内容
        /// </summary>
        /// <param name="scene"></param>
        public void hideSecen(Scene scene)
        {
            List<SceneObject> slist = new List<SceneObject>();
            foreach (var g in scene.GetRootGameObjects())
            {
                SceneObject sceneObject = new SceneObject();
                sceneObject.obj = g;
                sceneObject.visable = g.activeSelf;
                sceneObject.hiden();
                slist.Add(sceneObject);
            }
            hidenScenes.Add(scene, slist);

        }

        public Scene scene(string name)
        {
            return SceneManager.GetSceneByName(name);
        }

        /// <summary>
        /// 显示场景
        /// </summary>
        /// <param name="scene"></param>
        public void visableScene(Scene scene)
        {
            if (hidenScenes.ContainsKey(scene))
            {
                var list = hidenScenes[scene];
                foreach (var l in list)
                    l.show();

                hidenScenes.Remove(scene);
            }
        }

        /// <summary>
        /// 激活场景
        /// </summary>
        /// <param name="name"> 场景的名字，必需是被加载的场景</param>
        public void SetActiveScene(string name)
        {
            Scene sc = SceneManager.GetSceneByName(name);
            if (sc != null && sc.isLoaded)
                SceneManager.SetActiveScene(sc);
        }

        /// <summary>
        ///  unity 发出
        /// 完成场景加载
        /// </summary>
        /// <param name="scene"></param>
        /// <param name="mode"></param>
        void OnSceneLoaded(Scene scene, LoadSceneMode mode)
        {

            //加载后是否隐藏起来，需要时再显示
            if (loadscene.ContainsKey(scene.name))
            {
                if (!loadscene[scene.name])
                    hideSecen(scene);
                //完成后从表中加载表
                loadscene.Remove(scene.name);
            }

            //加载时，是否同时激活场景
            if (activeScene == scene.name)
                SceneManager.SetActiveScene(scene);

            //管理列表中
            if (!loadedScenes.Contains(scene.name))
                loadedScenes.Add(scene.name);


        }

        /// <summary>
        /// unity 发出
        /// 完成移除场景资源
        /// </summary>
        /// <param name="scene">原场景对象 </param>
        /// 
        void OnSceneUnLoaded(Scene scene)
        {
            loadedScenes.Remove(scene.name);
        }


        /// <summary>
        ///  unity 发出
        /// 更换活动的场景
        /// </summary>
        /// <param name="scene">原场景</param>
        /// <param name="nscene">新场景</param>
        /// 
        void OnActiveSceneChanged(Scene scene, Scene nscene)
        {
            previousScene = scene.name;
        }


        /// <summary>
        /// 异步加载场景并转换，带进度数据 sceneloadingProgress
        /// </summary>
        /// <param name="name"> 场景名称 必需是在buider管理中的名字</param> 
        ///  <param name="Activation">加载后是否激活</param>
        /// <param name="visable">加载后隐藏</param>
        public void LoadSceneAsync(string name, bool Activation = true, bool visable = true)
        {
            KF.Log("framework  async load scene :" + name);
            loadscene.Add(name, visable);
            StartCoroutine(LoadToScene(name));
        }



        IEnumerator LoadToScene(string nextSceneName)
        {
            AsyncOperation async = SceneManager.LoadSceneAsync(nextSceneName);
            async.allowSceneActivation = false;
            while (!async.isDone)
            {
                if (onLoadProgresss != null)
                    onLoadProgresss(nextSceneName, async.progress);
            }
            if (onLoadProgresss != null)
                onLoadProgresss(nextSceneName, async.progress);
            yield return null;
        }

    }

}

